package design.mode.chapter3.item3.version1.Aggregator;

import design.mode.chapter3.item3.version1.domain.RequestInfo;
import design.mode.chapter3.item3.version1.domain.RequestStat;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 是一个工具类，负责各种统计数据的计算，比如响应时间的最大值、最小值、平均值、百分位值、接口访问次数、tps。
 * 要添加新的统计功能的时候，我们需要修改 aggregate() 函数代码。
 * 一旦越来越多的统计功能添加进来之后，
 * 这个函数的代码量会持续增加，可读性、可维护性就变差了
 *
 */
public class Aggregator {


    public static RequestStat aggregate(List<RequestInfo> requestInfos, long durationInMillis) {
        double maxRespTime = Double.MIN_VALUE;
        double minRespTime = Double.MAX_VALUE;
        double avgRespTime = -1;
        double p999RespTime = -1;
        double p99RespTime = -1;
        double sumRespTime = 0;
        long count = 0;
        for (RequestInfo requestInfo : requestInfos) {
            ++count;
            double respTime = requestInfo.getResponseTime();
            if (maxRespTime < respTime) {
                maxRespTime = respTime;
            }
            if (minRespTime > respTime) {
                minRespTime = respTime;
            }
            sumRespTime += respTime;
        }
        if (count != 0) {
            avgRespTime = sumRespTime / count;
        }
        long tps = (long) (count / durationInMillis * 1000);
        Collections.sort(requestInfos, new Comparator<RequestInfo>() {
            @Override
            public int compare(RequestInfo o1, RequestInfo o2) {
                double diff = o1.getResponseTime() - o2.getResponseTime();
                if (diff < 0.0) {
                    return -1;
                } else if (diff > 0.0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });
        int idx999 = (int) (count * 0.999);
        int idx99 = (int) (count * 0.99);
        if (count != 0) {
            p999RespTime = requestInfos.get(idx999).getResponseTime();
            p99RespTime = requestInfos.get(idx99).getResponseTime();
        }
        RequestStat requestStat = new RequestStat();
        requestStat.setMaxResponseTime(maxRespTime);
        requestStat.setMinResponseTime(minRespTime);
        requestStat.setAvgResponseTime(avgRespTime);
        requestStat.setP999ResponseTime(p999RespTime);
        requestStat.setP99ResponseTime(p99RespTime);
        requestStat.setCount(count);
        requestStat.setTps(tps);
        return requestStat;
    }

    public static void main(String[] args) {
        RequestInfo requestInfo1 = new RequestInfo("11", 333D, 111L);
        RequestInfo requestInfo3 = new RequestInfo("22", 111D, 222L);
        RequestInfo requestInfo2 = new RequestInfo("22", 222D, 222L);
        List<RequestInfo> list = Arrays.asList(requestInfo1, requestInfo2, requestInfo3);
        list.stream().forEach(e -> {
            System.out.println(e.getResponseTime());
        });
        System.out.println("=============");
        Collections.sort(list, new Comparator<RequestInfo>() {
            @Override
            public int compare(RequestInfo o1, RequestInfo o2) {
                double diff = o2.getResponseTime() - o1.getResponseTime();
                if (diff < 0.0) {
                    return -1;
                } else if (diff > 0.0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });
        list.stream().forEach(e -> {
            System.out.println(e.getResponseTime());
        });
    }
}
